package com.share.payment.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.share.payment.config.AliPayConfig;
import com.share.common.core.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.Base64Utils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Map;

/**
 * 支付宝支付工具类
 *
 * @author share
 * @date 2024-04-16
 */
@Slf4j
@Component
public class AliPayUtils {

    @Autowired
    private AliPayConfig alipayConfig;

    @Value("${alipay.is-sandbox:true}")
    private boolean isSandbox;

    @Value("${alipay.seller-id:2088721029211324}")
    private String sellerId;

    /**
     * 生成支付二维码
     *
     * @param orderNo 订单号
     * @param amount  金额
     * @param subject 商品名称
     * @return Base64编码的二维码图片
     */
    public String generatePayQrCode(String orderNo, String amount, String subject) {
        try {

            log.info("开始创建支付宝支付订单，订单号：{}", orderNo);
            log.info("支付宝配置信息：gatewayUrl={}, appId={}",
                    alipayConfig.getGatewayUrl(), alipayConfig.getAppId());

            // 1. 创建支付宝客户端
            AlipayClient alipayClient = new DefaultAlipayClient(
                    alipayConfig.getGatewayUrl(),
                    alipayConfig.getAppId(),
                    alipayConfig.getPrivateKey(),
                    alipayConfig.getFormat(),
                    alipayConfig.getCharset(),
                    alipayConfig.getPublicKey(),
                    alipayConfig.getSignType()
            );

            // 2. 创建API对应的request
            AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();

            // 3. 构造请求参数
            JSONObject bizContent = new JSONObject();
            bizContent.put("out_trade_no", orderNo);
            bizContent.put("total_amount", amount);
            bizContent.put("subject", subject);
            bizContent.put("body", "充电宝归还");
            bizContent.put("timeout_express", "2m");

            request.setBizContent(bizContent.toString());
            request.setNotifyUrl(alipayConfig.getNotifyUrl());

            log.info("支付宝请求参数：{}", bizContent);

            // 4. 调用SDK生成二维码
            AlipayTradePrecreateResponse response = alipayClient.execute(request);
            log.info("支付宝响应：{}", response.getBody());

            if (response.isSuccess()) {
                String qrCode = response.getQrCode();
                log.info("生成二维码成功，二维码URL：{}", qrCode);

                // 确保返回完整的二维码URL
                if (!qrCode.startsWith("http")) {
                    qrCode = "https://qr.alipay.com/" + qrCode;
                }

                // 生成二维码图片
                String base64QrCode = generateQRCodeImage(qrCode);
                return base64QrCode;
            } else {
                log.error("支付宝预创建订单失败，错误码：{}，错误信息：{}",
                        response.getCode(), response.getMsg());
                throw new RuntimeException("支付宝预创建订单失败：" + response.getMsg());
            }

        } catch (AlipayApiException e) {
            log.error("创建支付宝支付订单失败", e);
            String errorMsg = String.format("支付宝API调用失败，错误码：%s，错误信息：%s", e.getErrCode(), e.getErrMsg());
            log.error(errorMsg);
            throw new ServiceException(errorMsg);
        } catch (Exception e) {
            log.error("创建支付宝支付订单失败", e);
            throw new ServiceException("创建支付宝支付订单失败：" + e.getMessage());
        }
    }

    /**
     * 生成二维码图片并转换为Base64
     */
    private String generateQRCodeImage(String text) throws WriterException, IOException {
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        BitMatrix bitMatrix = qrCodeWriter.encode(text, BarcodeFormat.QR_CODE, 300, 300);
        
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        MatrixToImageWriter.writeToStream(bitMatrix, "PNG", outputStream);
        
        return "data:image/png;base64," + Base64Utils.encodeToString(outputStream.toByteArray());
    }

    /**
     * 查询支付状态
     *
     * @param orderNo 订单号
     * @return 交易状态
     */
    public String queryPayStatus(String orderNo) {
        try {
            log.info("开始查询订单状态，订单号：{}", orderNo);
            
            // 1. 创建支付宝客户端
            AlipayClient alipayClient = new DefaultAlipayClient(
                    alipayConfig.getGatewayUrl(),
                    alipayConfig.getAppId(),
                    alipayConfig.getPrivateKey(),
                    alipayConfig.getFormat(),
                    alipayConfig.getCharset(),
                    alipayConfig.getPublicKey(),
                    alipayConfig.getSignType()
            );

            // 2. 创建API对应的request
            AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
            
            // 3. 构造请求参数
            JSONObject bizContent = new JSONObject();
            bizContent.put("out_trade_no", orderNo);
            
            request.setBizContent(bizContent.toString());
            
            log.info("支付宝查询订单请求参数：{}", bizContent);
            
            // 4. 调用SDK查询订单状态
            AlipayTradeQueryResponse response = alipayClient.execute(request);
            log.info("支付宝查询订单响应：{}", response.getBody());
            
            if (response.isSuccess()) {
                String tradeStatus = response.getTradeStatus();
                log.info("订单状态：{}", tradeStatus);
                
                // 根据支付宝返回的交易状态判断订单是否支付成功
                if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) {
                    return "PAID";
                } else if ("WAIT_BUYER_PAY".equals(tradeStatus)) {
                    return "UNPAID";
                } else if ("TRADE_CLOSED".equals(tradeStatus)) {
                    return "CLOSED";
                } else {
                    return "UNKNOWN";
                }
            } else {
                log.error("支付宝查询订单失败，错误码：{}，错误信息：{}", 
                    response.getCode(), response.getMsg());
                
                // 处理交易不存在的错误
                if ("40004".equals(response.getCode()) && "ACQ.TRADE_NOT_EXIST".equals(response.getSubCode())) {
                    log.info("订单不存在或已关闭，订单号：{}", orderNo);
                    return "CLOSED";
                }
                
                return "ERROR";
            }
        } catch (AlipayApiException e) {
            log.error("支付宝API调用失败，错误码：{}，错误信息：{}", e.getErrCode(), e.getErrMsg());
            
            // 处理交易不存在的错误
            if ("40004".equals(e.getErrCode()) && e.getErrMsg().contains("ACQ.TRADE_NOT_EXIST")) {
                log.info("订单不存在或已关闭，订单号：{}", orderNo);
                return "CLOSED";
            }
            
            return "ERROR";
        } catch (Exception e) {
            log.error("查询订单状态失败", e);
            return "ERROR";
        }
    }

    /**
     * 验证回调签名
     *
     * @param params 回调参数
     * @return 验证结果
     */
    public boolean verifyCallback(Map<String, String> params) {
        try {
            boolean signVerified = AlipaySignature.rsaCheckV1(
                    params,
                    alipayConfig.getPublicKey(),
                    alipayConfig.getCharset(),
                    alipayConfig.getSignType()
            );

            if (signVerified) {
                log.info("支付宝回调签名验证成功");
                return true;
            } else {
                log.error("支付宝回调签名验证失败");
                return false;
            }
        } catch (AlipayApiException e) {
            log.error("支付宝回调签名验证异常", e);
            return false;
        }
    }
}